import tkinter as tk
from tkinter import filedialog, messagebox
from PIL import Image, ImageTk
import os
import numpy as np
import image_channels
import image_io
import image_transform
import config
import sys
from image_utils import language_data, logging
import image_utils as utils
import subprocess
from skimage import filters

def apply_global_threshold(image, threshold):
    """
    应用全局阈值处理到图像
    :param image: 输入图像，numpy数组
    :param threshold: 阈值
    :return: 处理后的二值图像
    """
    if len(image.shape) == 2:
        # 灰度图像
        binary_image = (image > threshold).astype(np.uint8) * 255
    else:
        # 彩色图像，对每个通道分别处理
        binary_image = np.zeros_like(image)
        for i in range(3):
            channel = image[:, :, i]
            binary_image[:, :, i] = (channel > threshold).astype(np.uint8) * 255
    return binary_image

def apply_motion_difference(image, shift_x, shift_y):
    """
    应用运动差异处理到图像
    :param image: 输入图像，numpy数组
    :param shift_x: X方向的偏移量
    :param shift_y: Y方向的偏移量
    :return: 处理后的图像
    """
    logging.info(f"应用运动差异处理，shift_x={shift_x}, shift_y={shift_y}")
    if len(image.shape) == 2:
        # 灰度图像
        shifted_image = np.roll(image, shift=(shift_y, shift_x), axis=(0, 1))
    else:
        # 彩色图像
        shifted_image = np.roll(image, shift=(shift_y, shift_x, 0), axis=(0, 1, 2))
    return shifted_image

def create_red_mask(image):
    """
    创建红色通道的掩码
    :param image: 输入图像
    :return: 红色区域掩码
    """
    if len(image.shape) == 2:
        return np.zeros(image.shape, dtype=bool)
    red_channel = image[:, :, 0]
    green_channel = image[:, :, 1]
    blue_channel = image[:, :, 2]
    # 定义红色区域的阈值条件
    mask = (red_channel > 150) & (green_channel < 100) & (blue_channel < 100)
    return mask

def apply_red_mask(image, mask):
    """
    应用红色掩码到图像
    :param image: 输入图像
    :param mask: 红色区域掩码
    :return: 处理后的图像
    """
    if len(image.shape) == 2:
        return image
    masked_image = image.copy()
    # 将非红色区域置为黑色
    masked_image[~mask] = 0
    return masked_image

def invert_image(image):
    """
    反转图像颜色
    :param image: 输入图像
    :return: 颜色反转后的图像
    """
    return 255 - image

class ImageProcessor:
    def __init__(self, master):
        """
        初始化图像处理器
        :param master: Tkinter根窗口
        """
        self.master = master
        self.current_language = language_data["current_language"]
        master.title(language_data[self.current_language]['app_title'])

        # 图像相关属性
        self.original_image = None  # 原始图像备份
        self.image = None  # 当前处理的图像
        self.image_path = ""  # 图像文件路径
        
        # 裁剪相关属性
        self.rect_start_x = None
        self.rect_start_y = None
        self.rect_end_x = None
        self.rect_end_y = None
        self.is_drawing = False
        self.current_rect = None
        self.crop_region = None

        self.create_widgets()  # 创建UI组件

    def create_widgets(self):
        """创建应用程序的界面组件"""
        # 创建菜单栏
        menubar = tk.Menu(self.master)
        self.master.config(menu=menubar)

        # 文件菜单
        file_menu = tk.Menu(menubar, tearoff=0)
        file_menu.add_command(label=language_data[self.current_language]['open_original'], 
                             command=self.open_as_original)
        file_menu.add_command(label=language_data[self.current_language]['open_grayscale'], 
                             command=self.open_as_gray)
        file_menu.add_command(label=language_data[self.current_language]['merge_channels'], 
                             command=self.merge_channels)
        file_menu.add_command(label=language_data[self.current_language]['save_image'], 
                             command=self.save_image)
        file_menu.add_separator()
        
        # 语言子菜单
        language_menu = tk.Menu(file_menu, tearoff=0)
        self.language_var = tk.StringVar(value=self.current_language)
        language_menu.add_radiobutton(label="中文", variable=self.language_var, 
                                     value="zh", command=self.change_language)
        language_menu.add_radiobutton(label="English", variable=self.language_var, 
                                     value="en", command=self.change_language)
        file_menu.add_cascade(label=language_data[self.current_language]['language'], 
                             menu=language_menu)
        file_menu.add_command(label=language_data[self.current_language]['exit'], 
                             command=self.master.quit)
        menubar.add_cascade(label=language_data[self.current_language]['file'], 
                           menu=file_menu)

        # 信息菜单
        info_menu = tk.Menu(menubar, tearoff=0)
        info_menu.add_command(label=language_data[self.current_language]['details'], 
                             command=self.show_image_details)
        menubar.add_cascade(label=language_data[self.current_language]['info'], 
                           menu=info_menu)

        # 编辑菜单
        edit_menu = tk.Menu(menubar, tearoff=0)
        edit_menu.add_command(label=language_data[self.current_language]['crop'], 
                             command=self.crop_image)
        edit_menu.add_command(label=language_data[self.current_language]['reset'], 
                             command=self.reset_image)
        edit_menu.add_command(label=language_data[self.current_language]['brightness_adjustment'], 
                             command=self.adjust_brightness)
        edit_menu.add_command(label=language_data[self.current_language]['global_threshold'], 
                             command=self.apply_global_threshold_processing)
        edit_menu.add_command(label=language_data[self.current_language]['motion_difference'], 
                             command=self.apply_motion_difference_processing)
        edit_menu.add_command(label=language_data[self.current_language]['red_mask'], 
                             command=self.create_and_apply_red_mask)
        edit_menu.add_command(label=language_data[self.current_language]['invert'], 
                             command=self.invert_image_processing)
        menubar.add_cascade(label=language_data[self.current_language]['edit'], 
                           menu=edit_menu)

        # 分割菜单
        split_menu = tk.Menu(menubar, tearoff=0)
        split_menu.add_command(label=language_data[self.current_language]['split_channels'], 
                              command=self.split_image_channels)
        menubar.add_cascade(label=language_data[self.current_language]['split'], 
                           menu=split_menu)

        # 创建画布用于显示图像
        self.canvas = tk.Canvas(self.master, width=600, height=400, bg='gray')
        self.canvas.pack()

        # 绑定鼠标事件
        self.canvas.bind("<Button-1>", self.on_mouse_down)
        self.canvas.bind("<B1-Motion>", self.on_mouse_move)
        self.canvas.bind("<ButtonRelease-1>", self.on_mouse_up)

    def change_language(self):
        """切换应用程序语言"""
        self.current_language = self.language_var.get()
        utils.write_language_data(language_data, "current_language", self.current_language)
        logging.info(f"当前语言已切换为{self.current_language}。")
        confirm = messagebox.askyesno(
            language_data[self.current_language]['confirm_restart'],
            language_data[self.current_language]['restart_warning']
        )
        if confirm:
            self.master.destroy()
            subprocess.Popen([sys.executable] + sys.argv)

    def merge_channels(self):
        """合并多个图像通道"""
        file_paths = filedialog.askopenfilenames()
        if not file_paths:
            return
        if len(file_paths) == 1:
            messagebox.showerror(
                language_data[self.current_language]['error'],
                language_data[self.current_language]['single_file_error']
            )
            return
        try:
            self.image = image_channels.merge_image_channels(file_paths)
            self.original_image = self.image.copy()
            self.display_image()
        except ValueError as e:
            messagebox.showerror(language_data[self.current_language]['error'], str(e))

    def split_image_channels(self):
        """分割图像通道"""
        if self.image is None:
            messagebox.showinfo(
                language_data[self.current_language]['error'],
                language_data[self.current_language]['no_image_loaded']
            )
            return
        if len(self.image.shape) == 2:
            messagebox.showinfo(
                language_data[self.current_language]['error'],
                language_data[self.current_language]['single_channel_error']
            )
            return
        try:
            channels = image_channels.split_image_channels(self.image)
        except ValueError as e:
            messagebox.showinfo(language_data[self.current_language]['error'], str(e))
            return
        
        for i, channel in enumerate(channels):
            window = tk.Toplevel(self.master)
            window.title(language_data[self.current_language]['channel_title'].format(i))
            canvas = tk.Canvas(window, width=300, height=300)
            canvas.pack()
            
            def save_channel(channel, index):
                save_path = filedialog.asksaveasfilename(
                    defaultextension=config.DEFAULT_SAVE_FORMAT
                )
                if not save_path:
                    return
                image_io.save_image(channel, save_path)
                messagebox.showinfo(
                    language_data[self.current_language]['success'],
                    language_data[self.current_language]['channel_saved'].format(index, save_path)
                )
            
            save_button = tk.Button(
                window,
                text=language_data[self.current_language]['save_channel'],
                command=lambda c=channel, i=i: save_channel(c, i)
            )
            save_button.pack()
            
            # 显示通道图像
            image = Image.fromarray(channel)
            canvas_width = canvas.winfo_width()
            canvas_height = canvas.winfo_height()
            image_width, image_height = image.size
            scale = min(canvas_width / image_width, canvas_height / image_height)
            
        if scale < 1:
            new_size = (int(image_width * scale), int(image_height * scale))
            image = image.resize(new_size, Image.LANCZOS)
        else:
            new_size = (int(image_width * scale), int(image_height * scale))
            image = image.resize(new_size, Image.BICUBIC)
            
            photo = ImageTk.PhotoImage(image)
            x = (canvas_width - new_size[0]) // 2
            y = (canvas_height - new_size[1]) // 2
            canvas.create_image(x, y, anchor=tk.NW, image=photo)
            canvas.image = photo  # 保持引用
            
            # 添加通道标题
            title = f"Channel {i}"
            canvas.create_text(
                canvas_width//2, 15, 
                text=title, 
                font=("Arial", 15), 
                fill="black"
            )

    def show_image_details(self):
        """显示图像详细信息"""
        if self.image is None:
            messagebox.showinfo(
                language_data[self.current_language]['error'],
                language_data[self.current_language]['no_image_loaded']
            )
            return

        filename = os.path.basename(self.image_path)
        total_pixels = self.image.size
        shape = self.image.shape
        channels = shape[2] if len(shape) == 3 else 1
        dtype = self.image.dtype

        details = language_data[self.current_language]['info_str'].format(
            filename, total_pixels, shape, channels, dtype
        )

        messagebox.showinfo("INFO", details)

    def on_mouse_down(self, event):
        """鼠标按下事件处理"""
        if self.current_rect and not self.is_drawing:
            self.canvas.delete(self.current_rect)
            self.current_rect = None
        else:
            self.rect_start_x = event.x
            self.rect_start_y = event.y
            self.is_drawing = True

    def on_mouse_move(self, event):
        """鼠标移动事件处理"""
        if self.is_drawing:
            if self.current_rect:
                self.canvas.delete(self.current_rect)
            self.current_rect = self.canvas.create_rectangle(
                self.rect_start_x, self.rect_start_y, 
                event.x, event.y, 
                outline="red"
            )

    def on_mouse_up(self, event):
        """鼠标释放事件处理"""
        self.rect_end_x, self.rect_end_y = event.x, event.y
        self.is_drawing = False
        self.crop_region = (
            min(self.rect_start_y, self.rect_end_y),
            max(self.rect_start_y, self.rect_end_y),
            min(self.rect_start_x, self.rect_end_x),
            max(self.rect_start_x, self.rect_end_x)
        )

    def open_as_original(self):
        """以原始格式打开图像"""
        self.image_path = filedialog.askopenfilename()
        if not self.image_path:
            return
        self.image = image_io.load_image(self.image_path)
        self.original_image = self.image.copy()
        self.display_image()

    def open_as_gray(self):
        """以灰度格式打开图像"""
        self.image_path = filedialog.askopenfilename()
        if not self.image_path:
            return
        self.image = image_io.load_image(self.image_path, as_gray=True)
        self.original_image = self.image.copy()
        self.display_image()

    def display_image(self):
        """在画布上显示当前图像"""
        if self.image is None:
            return

        image = Image.fromarray(self.image)
        canvas_width = self.canvas.winfo_width()
        canvas_height = self.canvas.winfo_height()
        image_width, image_height = image.size
        scale = min(canvas_width / image_width, canvas_height / image_height)

        if scale < 1:
            new_size = (int(image_width * scale), int(image_height * scale))
            image = image.resize(new_size, Image.LANCZOS)
        else:
            new_size = (int(image_width * scale), int(image_height * scale))
            image = image.resize(new_size, Image.BICUBIC)

        photo = ImageTk.PhotoImage(image)
        self.canvas.delete("all")
        x = (canvas_width - new_size[0]) // 2
        y = (canvas_height - new_size[1]) // 2
        self.canvas.create_image(x, y, anchor=tk.NW, image=photo)
        self.canvas.image = photo  # 保持引用

    def save_image(self):
        """保存当前图像"""
        if self.image is None:
            messagebox.showinfo(
                language_data[self.current_language]['error'],
                language_data[self.current_language]['no_image_to_be_saved']
            )
            return

        save_path = filedialog.asksaveasfilename(
            defaultextension=config.DEFAULT_SAVE_FORMAT
        )
        if not save_path:
            return

        image_io.save_image(self.image, save_path)
        messagebox.showinfo(
            language_data[self.current_language]['success'],
            language_data[self.current_language]['image_saved'].format(save_path)
        )

    def crop_image(self):
        """裁剪图像"""
        if self.image is None:
            messagebox.showinfo(
                language_data[self.current_language]['error'],
                language_data[self.current_language]['no_image_to_be_cropped']
            )
            return

        if hasattr(self, 'crop_region') and self.current_rect:
            image_height, image_width = self.image.shape[:2]
            canvas_width = self.canvas.winfo_width()
            canvas_height = self.canvas.winfo_height()
            scale = min(canvas_width / image_width, canvas_height / image_height)
            offset_x = (canvas_width - image_width * scale) // 2
            offset_y = (canvas_height - image_height * scale) // 2

            # 计算实际裁剪区域
            real_crop_region = (
                int((self.crop_region[0] - offset_y) / scale),
                int((self.crop_region[1] - offset_y) / scale),
                int((self.crop_region[2] - offset_x) / scale),
                int((self.crop_region[3] - offset_x) / scale)
            )

            cropped_image = image_transform.crop_image(self.image, real_crop_region)
            if cropped_image is not None:
                self.image = cropped_image
                self.display_image()
                self.canvas.delete(self.current_rect)
                self.current_rect = None
                del self.crop_region
            else:
                messagebox.showinfo(
                    language_data[self.current_language]['error'],
                    language_data[self.current_language]['crop_failed']
                )
        else:
            messagebox.showinfo(
                language_data[self.current_language]['error'],
                language_data[self.current_language]['no_crop_area']
            )

    def reset_image(self):
        """重置图像到原始状态"""
        if not self.image_path:
            messagebox.showinfo(
                language_data[self.current_language]['error'],
                language_data[self.current_language]['no_reset_image']
            )
            return
        self.image = image_io.load_image(self.image_path)
        self.original_image = self.image.copy()
        self.display_image()

    def adjust_brightness(self):
        """调整图像亮度"""
        if self.image is None:
            messagebox.showinfo(
                language_data[self.current_language]['error'],
                language_data[self.current_language]['no_image_loaded']
            )
            return

        def on_ok():
            self.apply_brightness_adjustment(int(brightness_scale.get()))
            top.destroy()

        def on_scale_change(value):
            self.apply_brightness_adjustment(int(value))

        top = tk.Toplevel(self.master)
        top.title(language_data[self.current_language]['brightness_adjustment'])

        label = tk.Label(top, text=language_data[self.current_language]['brightness_value'])
        label.pack()

        brightness_scale = tk.Scale(
            top, from_=0, to=200, orient=tk.HORIZONTAL, command=on_scale_change
        )
        brightness_scale.set(100)
        brightness_scale.pack()

        ok_button = tk.Button(top, text=language_data[self.current_language]['ok'], command=on_ok)
        ok_button.pack()

    def apply_brightness_adjustment(self, value):
        """应用亮度调整"""
        try:
            adjusted_image = self.original_image.astype(np.float64) * (value / 100.0)
            adjusted_image = np.clip(adjusted_image, 0, 255).astype(np.uint8)
            self.image = adjusted_image
            self.display_image()
        except Exception as e:
            messagebox.showerror(
                language_data[self.current_language]['error'],
                language_data[self.current_language]['brightness_adjustment_error']
            )

    def apply_global_threshold_processing(self):
        """应用全局阈值处理"""
        if self.image is None:
            messagebox.showinfo(
                language_data[self.current_language]['error'],
                language_data[self.current_language]['no_image_loaded']
            )
            return

        def on_ok():
            threshold = int(threshold_scale.get())
            self.image = apply_global_threshold(self.original_image, threshold)
            self.display_image()
            top.destroy()

        def on_scale_change(value):
            threshold = int(value)
            self.image = apply_global_threshold(self.original_image, threshold)
            self.display_image()

        top = tk.Toplevel(self.master)
        top.title(language_data[self.current_language]['global_threshold'])

        label = tk.Label(top, text="Threshold Value (0-255)")
        label.pack()

        threshold_scale = tk.Scale(
            top, from_=0, to=255, orient=tk.HORIZONTAL, command=on_scale_change
        )
        threshold_scale.set(128)
        threshold_scale.pack()

        ok_button = tk.Button(top, text=language_data[self.current_language]['ok'], command=on_ok)
        ok_button.pack()

    def apply_motion_difference_processing(self):
        """应用运动差异处理"""
        if self.image is None:
            messagebox.showinfo(
                language_data[self.current_language]['error'],
                language_data[self.current_language]['no_image_loaded']
            )
            return

        def on_ok():
            shift_x = int(shift_x_scale.get())
            shift_y = int(shift_y_scale.get())
            self.image = apply_motion_difference(self.image, shift_x, shift_y)
            self.display_image()
            top.destroy()

        def on_scale_change_x(value):
            shift_x = int(value)
            shift_y = int(shift_y_scale.get())
            self.image = apply_motion_difference(self.image, shift_x, shift_y)
            self.display_image()

        def on_scale_change_y(value):
            shift_x = int(shift_x_scale.get())
            shift_y = int(value)
            self.image = apply_motion_difference(self.image, shift_x, shift_y)
            self.display_image()

        top = tk.Toplevel(self.master)
        top.title(language_data[self.current_language]['motion_difference'])

        label_x = tk.Label(top, text="Shift X Value")
        label_x.pack()

        shift_x_scale = tk.Scale(
            top, from_=-100, to=100, orient=tk.HORIZONTAL, command=on_scale_change_x
        )
        shift_x_scale.set(0)
        shift_x_scale.pack()

        label_y = tk.Label(top, text="Shift Y Value")
        label_y.pack()

        shift_y_scale = tk.Scale(
            top, from_=-100, to=100, orient=tk.HORIZONTAL, command=on_scale_change_y
        )
        shift_y_scale.set(0)
        shift_y_scale.pack()

        ok_button = tk.Button(top, text=language_data[self.current_language]['ok'], command=on_ok)
        ok_button.pack()

    def create_and_apply_red_mask(self):
        """创建并应用红色掩码"""
        if self.image is None:
            messagebox.showinfo(
                language_data[self.current_language]['error'],
                language_data[self.current_language]['no_image_loaded']
            )
            return
        try:
            mask = create_red_mask(self.image)  # 确保 create_red_mask 函数已定义
            self.image = apply_red_mask(self.image, mask)
            self.display_image()
        except Exception as e:
            messagebox.showerror("Error", str(e))

    def invert_image_processing(self):
        """反转图像颜色"""
        if self.image is None:
            messagebox.showinfo(
                language_data[self.current_language]['error'],
                language_data[self.current_language]['no_image_loaded']
            )
            return
        self.image = invert_image(self.image)
        self.display_image()

# 创建主窗口并运行应用程序
if __name__ == "__main__":
    root = tk.Tk()
    app = ImageProcessor(root)
    root.mainloop()